<!-- @format -->
<!-- 滚动列表组件 (支持自动滚+手动滚+无缝循环) -by wzy -->

<template>
    <div
        class="view-box"
        ref="view-box"
        @mouseenter="marqyeeEnter(true)"
        @mouseleave="marqyeeLeave(mouseLeave)"
        @mousewheel.prevent="marqyeeWheel($event)"
    >
        <div
            ref="scroll-box"
            :style="{
                transform: transform
            }"
        >
            <slot v-for="i in 2" :key="'dom' + i"></slot>
        </div>
    </div>
</template>

<script>
export default {
    name: 'ScrollList',
    data() {
        return {
            timer: null, //定时器标识
            doms: [], //滚动盒子的dom
            width: 0, //滚动盒子左侧的水平位置
            height: 0, //滚动盒子顶部的垂直高度
            scrollHeight: 0, //滚动盒子的高度(2个盒子的累加高)
            tempHeight: 0, //用户手动滚动产生的临时滚动盒顶部高度
            viewHeight: 0, //可视区域高度(固定值)
            marqyeeStop: false, //是否停止滚动
            mouseLeave: true, //鼠标移出时 是否继续滚动
            wheelScroll: true //鼠标滚动时 是否继续滚动
        };
    },
    props: {
        data: {
            //遍历的数组
            type: Array
        },
        display: {
            //容器盒子的展示类型(比如table时就传table)
            type: String,
            default: 'block'
        },
        mouseMethod: {
            //启用鼠标移入移出事件
            type: Boolean,
            default: false
        },
        initPosition: {
            //滚动起始位置
            type: Number,
            default: 0
        },
        scrollSpeed: {
            //滚动速度 值越大越快
            type: Number,
            default: 0.5
        },
        idlerWheelSpeed: {
            //滚轮速度, 大于0才支持手动滚
            type: Number,
            default: 0
        }
    },
    created() {
        // 设置初始高度
        if (this.initPosition) {
            this.height = this.initPosition;
        }
    },
    mounted() {
        // setTimeout(() => {
        this.isScroll();
        // }, 1200);
    },
    watch: {
        data: {
            // 外层数据发生改变的时候重置高度
            handler() {
                this.height = this.initPosition;
                this.isScroll();
            }
        }
    },
    computed: {
        transform: function () {
            return 'translate3d(0,' + parseFloat(`${this.height}`) + 'px,0)';
        },
        // 滚动盒子底部垂直高度(随height改变而改变)
        b_height: function () {
            this.calcSize();
            return this.height + this.scrollHeight;
        }
    },
    methods: {
        // 是否可滚
        isScroll() {
            this.$nextTick(() => {
                this.calcSize();
                // 内容没有超出视口高度时 不滚动
                if (this.scrollHeight / 2 < this.viewHeight) {
                    this.doms[1].style.visibility = 'hidden'; // 保留高度
                    this.mouseLeave = false; // 取消鼠标移出事件
                    this.wheelScroll = false; // 取消滚轮事件
                    clearTimeout(this.timer);
                    console.log('不满足滚动条件');
                }
                // 如果超出 让其可滚
                else {
                    this.doms[1].style.visibility = 'visible';
                    this.mouseLeave = true;
                    this.wheelScroll = true;
                    this.continue();
                }
            });
        },
        // 鼠标移入
        marqyeeEnter(bol) {
            if (bol) {
                clearTimeout(this.timer);
            }
        },
        // 鼠标移出
        marqyeeLeave(bol) {
            if (bol) {
                // 移出后显示第二项的dom(滚动盒子高度恢复)
                if (this.doms[1].style.display == 'none') {
                    this.doms[1].style.display = this.display;
                }
                if (this.tempHeight) {
                    this.height = this.tempHeight;
                }
                this.continue();
            }
        },
        // 自动滚
        marqyeeMove() {
            if (this.marqyeeStop) return;
            this.calcSize();
            // 用户手动滚 且 滚超一个盒子的高度时
            if (
                this.tempHeight &&
                this.tempHeight <= -(this.scrollHeight / 2)
            ) {
                this.height = this.tempHeight + this.scrollHeight / 2;
            } else {
                this.height -= this.scrollSpeed;
            }
            //  刚好滚出一个盒子的时候重新到起点 营造无限循环的错觉
            if (this.height <= -(this.scrollHeight / 2)) {
                this.height = this.initPosition;
            }
            this.continue();
            // 置空临时高度
            this.tempHeight = 0;
        },
        // 手动滚
        marqyeeWheel(el) {
            if (!this.wheelScroll) return;
            // 滚轮往下滚
            if (el.wheelDeltaY < 0) {
                this.height = this.height - this.idlerWheelSpeed;
                // 如果触底
                if (this.b_height <= this.viewHeight) {
                    this.doms[1].style.display = 'none'; // 隐藏第二项的盒子(滚动盒子高度减半)
                    this.calcSize();
                    this.height = -this.scrollHeight + this.viewHeight;
                }
            }
            // 滚轮往上滚
            else {
                this.height = this.height + this.idlerWheelSpeed;
                // 如果触顶
                if (this.height >= this.initPosition) {
                    this.doms[1].style.display = 'none';
                    this.height = this.initPosition;
                }
            }
            // 保留当前用户滚动后的高度
            this.tempHeight = this.height;
        },
        // 获取盒子dom和高度
        calcSize() {
            if (!this.$refs['scroll-box'] || !this.$refs['view-box']) return;
            this.doms = this.$refs['scroll-box'].children;
            this.scrollHeight = parseFloat(
                this.$refs['scroll-box'].offsetHeight
            );
            this.viewHeight = parseFloat(this.$refs['view-box'].offsetHeight);

            console.log(
                ' this.viewHeight',
                this.viewHeight,
                'scrollHeight',
                this.scrollHeight
            );
        },
        // 继续滚动
        continue() {
            clearTimeout(this.timer);
            this.timer = setTimeout(this.marqyeeMove.bind(this), 1000 / 60);
        }
    },
    unmounted() {
        clearTimeout(this.timer);
        this.timer = null;
        this.marqyeeStop = true;
    }
};
</script>
<style scoped>
.view-box {
    position: relative;
    overflow: hidden;
    width: 100%;
    height: 100%;
}
</style>
